package com.xyht.sca_s.student_manage_system.modules.stampRegistration.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.data.PictureRenderData;
import com.deepoove.poi.data.PictureType;
import com.deepoove.poi.data.Pictures;
import com.deepoove.poi.policy.PictureRenderPolicy;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.spire.doc.Document;
import com.spire.doc.FileFormat;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonCodeEnum;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonResult;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ExceptionCast;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ResponseResult;
import com.xyht.sca_s.student_manage_system.common.util.ApiModelUtil;
import com.xyht.sca_s.student_manage_system.common.util.CacheUtil;
import com.xyht.sca_s.student_manage_system.common.util.TimeUtil;
import com.xyht.sca_s.student_manage_system.modules.common.constant.FileSavePathConstant;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.AppTypeEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.RangeTypeEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.myEnum.TipsTypeEnum;
import com.xyht.sca_s.student_manage_system.modules.newTips.util.NewTipsUtil;
import com.xyht.sca_s.student_manage_system.modules.stampRegistration.entity.SmsStampRegistration;
import com.xyht.sca_s.student_manage_system.modules.stampRegistration.entity.SmsStampRegistrationDetail;
import com.xyht.sca_s.student_manage_system.modules.stampRegistration.entity.SmsStampRegistrationProcess;
import com.xyht.sca_s.student_manage_system.modules.stampRegistration.entity.dto.*;
import com.xyht.sca_s.student_manage_system.modules.stampRegistration.entity.vo.*;
import com.xyht.sca_s.student_manage_system.modules.stampRegistration.mapper.SmsStampRegistrationDetailMapper;
import com.xyht.sca_s.student_manage_system.modules.stampRegistration.mapper.SmsStampRegistrationMapper;
import com.xyht.sca_s.student_manage_system.modules.stampRegistration.mapper.SmsStampRegistrationMpjMapper;
import com.xyht.sca_s.student_manage_system.modules.stampRegistration.mapper.SmsStampRegistrationProcessMapper;
import com.xyht.sca_s.student_manage_system.modules.stampRegistration.service.SmsStampRegistrationService;
import com.xyht.sca_s.student_manage_system.modules.user.entity.SmsRole;
import com.xyht.sca_s.student_manage_system.modules.user.entity.SmsUser;
import com.xyht.sca_s.student_manage_system.modules.user.mapper.SmsRoleMapper;
import com.xyht.sca_s.student_manage_system.modules.user.mapper.SmsUserMapper;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

import static com.xyht.sca_s.student_manage_system.common.util.ParamCheckUtil.isNullOrEmpty;
import static com.xyht.sca_s.student_manage_system.modules.stampRegistration.constant.StampIsExportProcessConstant.EXPORT_PROCESS_TRUE;
import static com.xyht.sca_s.student_manage_system.modules.stampRegistration.constant.StampObjectTypeConstant.STAMP_OBJECT_TYPE_PERSON;
import static com.xyht.sca_s.student_manage_system.modules.stampRegistration.constant.StampObjectTypeConstant.STAMP_OBJECT_TYPE_ROLE;
import static com.xyht.sca_s.student_manage_system.modules.stampRegistration.constant.StampStatusConstant.*;
import static com.xyht.sca_s.student_manage_system.modules.stampRegistration.constant.StampTypeConstant.*;
import static com.xyht.sca_s.student_manage_system.modules.student.constant.StudentInfoCommonConstant.PER_SHEET_NUM;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author XYHT
 * @since 2023-05-25
 */
@Service
public class SmsStampRegistrationServiceImpl extends ServiceImpl<SmsStampRegistrationMapper, SmsStampRegistration> implements SmsStampRegistrationService {
    @Resource
    private FileSavePathConstant fileSavePathConstant;
    @Autowired
    private SmsStampRegistrationMapper smsStampRegistrationMapper;
    @Autowired
    private SmsStampRegistrationProcessMapper smsStampRegistrationProcessMapper;
    @Autowired
    private SmsStampRegistrationDetailMapper smsStampRegistrationDetailMapper;
    @Autowired
    private SmsStampRegistrationMpjMapper smsStampRegistrationMpjMapper;
    @Autowired
    private CacheUtil cacheUtil;
    @Autowired
    private NewTipsUtil newTipsUtil;
    @Autowired
    private SmsUserMapper smsUserMapper;
    @Autowired
    private ApiModelUtil apiModelUtil;
    @Autowired
    private SmsRoleMapper smsRoleMapper;

    @Override
    @Transactional
    public ResponseResult addStampRegistration(String userId, SmsStampRegistrationDto stampRegistrationDto) {
        //先判断流程是否存在
        List<SmsStampRegistrationProcess> fillProcessList = smsStampRegistrationProcessMapper.selectList(
                new QueryWrapper<SmsStampRegistrationProcess>()
                .lambda()
                .eq(SmsStampRegistrationProcess::getProcessIsUse,true)
                .eq(SmsStampRegistrationProcess::getProcessIsApplicantEdit,true)
                .orderByAsc(SmsStampRegistrationProcess::getProcessSort));
        if(fillProcessList != null && fillProcessList.size() > 0){
            if(stampRegistrationDto.getProcessList() == null || stampRegistrationDto.getProcessList().size() < 1){
                return CommonResult.failed(CommonCodeEnum.STAMP_REGISTRATION_ALLOW_USER_NOT_SETTING);
            }
        }

        //判断申请人是否将全部需要编辑流程填写
        List<SmsStampRegistrationProcess> filterList = fillProcessList
                .stream()
                .filter(process -> {
                    List<String> result = stampRegistrationDto.getProcessList()
                            .stream()
                            .filter(fillProcess -> fillProcess.getProcessId().equals(process.getId()))
                            .map(SmsStampRegistrationDetailDto::getId)
                            .collect(Collectors.toList());
                    //匹配的去除  未匹配的留下
                    if (result.size() > 0) {
                        return false;
                    } else {
                        return true;
                    }
                }).collect(Collectors.toList());
        if(filterList.size() > 0){
            return CommonResult.failed(CommonCodeEnum.STAMP_REGISTRATION_ALLOW_PROCESS_NOT_FILL);
        }

        //创建审批表
        SmsStampRegistration addStampRegistration = new SmsStampRegistration();
        BeanUtils.copyProperties(stampRegistrationDto,addStampRegistration);
        addStampRegistration.setStampApplyUserId(userId);
        addStampRegistration.setAllowStatus(STAMP_STATUS_WAIT_ALLOW);
        smsStampRegistrationMapper.insert(addStampRegistration);
        if(addStampRegistration.getId() == null){
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.FAIL));
        }
        String approvalId = addStampRegistration.getId();

        //创建审批流程表
        List<SmsStampRegistrationProcess> originProcessList = smsStampRegistrationProcessMapper.selectList(
                new QueryWrapper<SmsStampRegistrationProcess>()
                .lambda()
                .eq(SmsStampRegistrationProcess::getProcessIsUse,true)
                .orderByAsc(SmsStampRegistrationProcess::getProcessSort));
        if(originProcessList == null || originProcessList.size() < 1){
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.STAMP_REGISTRATION_PROCESS_NOT_SETTING));
        }
        int sort = 1;
        for (SmsStampRegistrationProcess process : originProcessList) {
            //判断管理员是否配置初始流程
            if(!process.getProcessIsApplicantEdit()){
                if(isNullOrEmpty(process.getProcessObjectType()) || isNullOrEmpty(process.getProcessObjectId())){
                    return CommonResult.failed(CommonCodeEnum.STAMP_REGISTRATION_PROCESS_NOT_SETTING);
                }
            }

            //创建审批流程表
            SmsStampRegistrationDetail addStampDetail = new SmsStampRegistrationDetail();
            addStampDetail.setProcessIsSign(process.getProcessIsSign());
            addStampDetail.setProcessIsStamp(process.getProcessIsStamp());
            addStampDetail.setProcessName(process.getProcessName());
            addStampDetail.setExamineId(approvalId);
            addStampDetail.setProcessId(process.getId());
            addStampDetail.setDetailSort(sort++);
            addStampDetail.setDetailAllowStatus(STAMP_STATUS_WAIT_ALLOW);
            addStampDetail.setProcessIsApplicantEdit(process.getProcessIsApplicantEdit());
            //申请人可编辑流程
            if(process.getProcessIsApplicantEdit()){
                List<SmsStampRegistrationDetailDto> filterProcessList = stampRegistrationDto.getProcessList()
                        .stream()
                        .filter(fillProcess -> fillProcess.getProcessId().equals(process.getId()))
                        .collect(Collectors.toList());
                if(filterProcessList.size() < 1){
                    ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.STAMP_REGISTRATION_ALLOW_PROCESS_NOT_FILL));
                }
                SmsStampRegistrationDetailDto fillProcessDto = filterProcessList.get(0);
                if(isNullOrEmpty(fillProcessDto.getProcessObjectId())){
                    ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
                }
                addStampDetail.setProcessObjectId(fillProcessDto.getProcessObjectId());
                addStampDetail.setProcessObjectType(STAMP_OBJECT_TYPE_PERSON);
            }else {
                addStampDetail.setProcessObjectId(process.getProcessObjectId());
                addStampDetail.setProcessObjectType(process.getProcessObjectType());
            }
            smsStampRegistrationDetailMapper.insert(addStampDetail);
        }

        //消息提醒
        //通知流程第一个节点
        SmsStampRegistrationDetail smsStampRegistrationDetail = smsStampRegistrationDetailMapper.selectOne(new QueryWrapper<SmsStampRegistrationDetail>()
                .lambda()
                .eq(SmsStampRegistrationDetail::getExamineId, approvalId)
                .eq(SmsStampRegistrationDetail::getDetailSort, 1)
                .orderByAsc(SmsStampRegistrationDetail::getDetailSort));
        RangeTypeEnum rangeTypeEnum;
        if(smsStampRegistrationDetail.getProcessIsApplicantEdit()){
            rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
        }else {
            if (smsStampRegistrationDetail.getProcessObjectType() == STAMP_OBJECT_TYPE_PERSON) {
                rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
            } else {
                rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_ROLE;
            }
        }
        List<String> rangeList = new ArrayList<>();
        rangeList.add(smsStampRegistrationDetail.getProcessObjectId());

        newTipsUtil.addNewTips(TipsTypeEnum.TIPS_TYPE_ENUM_ALLOW,
                userId,
                rangeTypeEnum,
                rangeList,
                AppTypeEnum.APP_TYPE_ENUM_STAMP_REGISTRATION,
                approvalId,
                smsStampRegistrationDetail.getId());
        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult cancelStampRegistration(String userId, SmsStampRegistrationCancelDto cancelDto) {
        if(isNullOrEmpty(cancelDto.getExamine_id())){
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        //查看审批表是否存在且是否为本人
        SmsStampRegistration stampRegistration = smsStampRegistrationMapper.selectOne(new QueryWrapper<SmsStampRegistration>()
        .lambda()
        .eq(SmsStampRegistration::getStampApplyUserId,userId)
        .eq(SmsStampRegistration::getId,cancelDto.getExamine_id()));
        if(stampRegistration == null || isNullOrEmpty(stampRegistration.getId())){
            return CommonResult.failed(CommonCodeEnum.STAMP_REGISTRATION_NOT_EXIST);
        }
        //判断审批状态,如果不是待审批状态 撤销失败
        if(stampRegistration.getAllowStatus() != STAMP_STATUS_WAIT_ALLOW){
            return CommonResult.failed(CommonCodeEnum.STAMP_REGISTRATION_CANCEL_FAIL_ALLOWED);
        }
//        //判断是否在审批中
//        List<SmsStampRegistrationDetail> detailList = smsStampRegistrationDetailMapper.selectList(new QueryWrapper<SmsStampRegistrationDetail>()
//        .lambda()
//        .eq(SmsStampRegistrationDetail::getExamineId,cancelDto.getExamine_id())
//        .eq(SmsStampRegistrationDetail::getDetailAllowStatus,STAMP_STATUS_PASS));
//        if(detailList != null && detailList.size() > 0){
//            return CommonResult.failed(CommonCodeEnum.STAMP_REGISTRATION_CANCEL_FAIL_ALLOWED);
//        }

        //撤回审批
        SmsStampRegistration cancelStampRegistration = new SmsStampRegistration();
        cancelStampRegistration.setAllowStatus(STAMP_STATUS_CANCEL);
        cancelStampRegistration.setId(cancelDto.getExamine_id());
        cancelStampRegistration.setProcessEndTime(new Date());
        smsStampRegistrationMapper.updateById(cancelStampRegistration);
        //修改节点
        SmsStampRegistrationDetail cancelStampRegistrationDetail = new SmsStampRegistrationDetail();
        cancelStampRegistrationDetail.setDetailAllowStatus(STAMP_STATUS_CANCEL);
        smsStampRegistrationDetailMapper.update(cancelStampRegistrationDetail, new QueryWrapper<SmsStampRegistrationDetail>()
                .lambda()
                .eq(SmsStampRegistrationDetail::getExamineId, cancelDto.getExamine_id())
        .eq(SmsStampRegistrationDetail::getDetailAllowStatus,STAMP_STATUS_WAIT_ALLOW));
        //消息通知
        newTipsUtil.cancelFinishTips(cancelDto.getExamine_id());
        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult allowStampRegistration(String userId, SmsStampRegistrationAllowDto allowDto) {
        if(isNullOrEmpty(allowDto.getExamine_id()) || isNullOrEmpty(allowDto.getDetailAllowStatus())
        || isNullOrEmpty(allowDto.getDetail_id())){
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        //判断审批状态只能为通过或驳回
        if(allowDto.getDetailAllowStatus() != STAMP_STATUS_PASS
                && allowDto.getDetailAllowStatus() != STAMP_STATUS_DENY){
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        //判断节点是否为待审批
        SmsStampRegistrationDetail smsStampRegistrationDetail = smsStampRegistrationDetailMapper.selectOne(new QueryWrapper<SmsStampRegistrationDetail>()
                .lambda()
                .eq(SmsStampRegistrationDetail::getExamineId, allowDto.getExamine_id())
                .eq(SmsStampRegistrationDetail::getId, allowDto.getDetail_id())
                .eq(SmsStampRegistrationDetail::getDetailAllowStatus, STAMP_STATUS_WAIT_ALLOW));

        if(smsStampRegistrationDetail == null || isNullOrEmpty(smsStampRegistrationDetail.getId())){
            return CommonResult.failed(CommonCodeEnum.STAMP_REGISTRATION_ALLOW_FAIL);
        }
        //判断该节点是否本人审批（防止跳节点审批)
        if(smsStampRegistrationDetail.getProcessObjectType() == STAMP_OBJECT_TYPE_PERSON){
            if(!smsStampRegistrationDetail.getProcessObjectId().equals(userId)){
                return CommonResult.failed(CommonCodeEnum.STAMP_REGISTRATION_ALLOW_FAIL);
            }
        }else {
            List<String> roleList = cacheUtil.getRoleList(userId);
            List<String> filterRoleList = roleList.stream().filter(role -> role.equals(smsStampRegistrationDetail.getProcessObjectId())).collect(Collectors.toList());
            if(filterRoleList.size() < 1){
                return CommonResult.failed(CommonCodeEnum.STAMP_REGISTRATION_ALLOW_FAIL);
            }
        }

        //如果是同一个人再判断上个节点是否完成审批
        if(!smsStampRegistrationDetail.getDetailSort().equals(1)){
            SmsStampRegistrationDetail preDetail = smsStampRegistrationDetailMapper.selectOne(new QueryWrapper<SmsStampRegistrationDetail>()
                    .lambda()
                    .eq(SmsStampRegistrationDetail::getExamineId, allowDto.getExamine_id())
                    .eq(SmsStampRegistrationDetail::getDetailSort, smsStampRegistrationDetail.getDetailSort() - 1));
            if(preDetail != null && !isNullOrEmpty(preDetail.getId())){
                if(preDetail.getDetailAllowStatus() != STAMP_STATUS_PASS){
                    return CommonResult.failed(CommonCodeEnum.STAMP_REGISTRATION_ALLOW_FAIL);
                }
            }
        }

        //审批节点修改
        SmsStampRegistrationDetail updateStampRegistrationDetail = new SmsStampRegistrationDetail();
        updateStampRegistrationDetail.setId(allowDto.getDetail_id());
        updateStampRegistrationDetail.setDetailAllowStatus(allowDto.getDetailAllowStatus());
        if(!isNullOrEmpty(allowDto.getDetailAllowOpinion())){
            updateStampRegistrationDetail.setDetailAllowOpinion(allowDto.getDetailAllowOpinion());
        }
        updateStampRegistrationDetail.setDetailAllowUserId(userId);
        updateStampRegistrationDetail.setDetailAllowTime(new Date());
        if(smsStampRegistrationDetail.getProcessIsSign()){
            if(isNullOrEmpty(allowDto.getDetailAllowSign())){
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }
            updateStampRegistrationDetail.setDetailAllowSign(allowDto.getDetailAllowSign());
        }
        if(smsStampRegistrationDetail.getProcessIsStamp()){
            if(isNullOrEmpty(allowDto.getDetailAllowStamp())){
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }
            updateStampRegistrationDetail.setDetailAllowStamp(allowDto.getDetailAllowStamp());
        }
        smsStampRegistrationDetailMapper.updateById(updateStampRegistrationDetail);
        //判断是否最后一个节点 是否驳回
        boolean is_done = false;
        Integer detailCount = smsStampRegistrationDetailMapper.selectCount(new QueryWrapper<SmsStampRegistrationDetail>()
                .lambda()
                .eq(SmsStampRegistrationDetail::getExamineId,allowDto.getExamine_id()));
        if(detailCount.equals(smsStampRegistrationDetail.getDetailSort()) || allowDto.getDetailAllowStatus() == STAMP_STATUS_DENY){
            is_done = true;
            SmsStampRegistration stampRegistration = new SmsStampRegistration();
            stampRegistration.setId(allowDto.getExamine_id());
            stampRegistration.setAllowStatus(allowDto.getDetailAllowStatus());
            stampRegistration.setProcessEndTime(new Date());
            smsStampRegistrationMapper.updateById(stampRegistration);
        }

        //节点驳回 重置其余节点状态
        if(allowDto.getDetailAllowStatus() == STAMP_STATUS_DENY){
            SmsStampRegistrationDetail approvalDetail = new SmsStampRegistrationDetail();
            approvalDetail.setDetailAllowStatus(STAMP_STATUS_DENY_FINISH);
            smsStampRegistrationDetailMapper.update(approvalDetail,new QueryWrapper<SmsStampRegistrationDetail>()
                    .lambda()
                    .eq(SmsStampRegistrationDetail::getExamineId,allowDto.getExamine_id())
                    .eq(SmsStampRegistrationDetail::getDetailAllowStatus,STAMP_STATUS_WAIT_ALLOW));
        }
        //消息通知
        if (is_done) {
            boolean result_status = false;
            if (allowDto.getDetailAllowStatus() == STAMP_STATUS_PASS) {
                result_status = true;
            }
            newTipsUtil.allowFinishTips(allowDto.getExamine_id(), userId, result_status);
        } else {
            SmsStampRegistrationDetail nextDetail =
                    smsStampRegistrationDetailMapper.selectOne(new QueryWrapper<SmsStampRegistrationDetail>()
                            .lambda()
                            .eq(SmsStampRegistrationDetail::getExamineId, allowDto.getExamine_id())
                            .eq(SmsStampRegistrationDetail::getDetailSort, smsStampRegistrationDetail.getDetailSort() + 1));
            RangeTypeEnum rangeTypeEnum;
            if(nextDetail.getProcessIsApplicantEdit()){
               rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
            }else {
                if (nextDetail.getProcessObjectType() == STAMP_OBJECT_TYPE_ROLE) {
                    rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_ROLE;
                }else {
                    rangeTypeEnum = RangeTypeEnum.RANGE_TYPE_ENUM_PERSON;
                }
            }
            List<String> rangeIDList = new ArrayList<>();
            rangeIDList.add(nextDetail.getProcessObjectId());
            newTipsUtil.allowContinueTips(allowDto.getExamine_id(),
                    userId,
                    rangeTypeEnum,
                    rangeIDList,nextDetail.getId());
        }
        return CommonResult.success();
    }

    @Override
    public ResponseResult getStampOriginSettingProcess() {
        List<SmsStampRegistrationOriginSettingVo> respList = smsStampRegistrationProcessMapper.selectList(
                new QueryWrapper<SmsStampRegistrationProcess>()
                        .lambda()
                        .eq(SmsStampRegistrationProcess::getProcessIsApplicantEdit, true)
                        .eq(SmsStampRegistrationProcess::getProcessIsUse, true)
                        .orderByAsc(SmsStampRegistrationProcess::getProcessSort))
                .stream()
                .map(process -> {
                    SmsStampRegistrationOriginSettingVo originSettingVo = new SmsStampRegistrationOriginSettingVo();
                    BeanUtils.copyProperties(process, originSettingVo);
                    return originSettingVo;
                })
                .collect(Collectors.toList());
        return CommonResult.success(respList);
    }

    @Override
    public ResponseResult getStampRegistrationDetail(String userId, String examineId) {
        if(isNullOrEmpty(examineId)){
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        SmsStampRegistration stampRegistration = smsStampRegistrationMapper.selectById(examineId);
        if(stampRegistration == null || isNullOrEmpty(stampRegistration.getId())){
            return CommonResult.failed(CommonCodeEnum.STAMP_REGISTRATION_NOT_EXIST);
        }

        SmsStampRegistrationVo stampRegistrationVo = new SmsStampRegistrationVo();
        BeanUtils.copyProperties(stampRegistration,stampRegistrationVo);

        stampRegistrationVo.setExamineId(stampRegistration.getId());

        SmsUser applyUserInfo = cacheUtil.getUserInfo(stampRegistration.getStampApplyUserId());
        SmsStampRegistrationUserVo applyUserVo = new SmsStampRegistrationUserVo();
        if(applyUserInfo != null){
            BeanUtils.copyProperties(applyUserInfo,applyUserVo);
        }
        stampRegistrationVo.setApplyUserInfo(applyUserVo);

        List<SmsStampRegistrationDetailVo> stampRegistrationDetailVos = smsStampRegistrationDetailMapper.selectList(
                new QueryWrapper<SmsStampRegistrationDetail>()
                .lambda()
                .eq(SmsStampRegistrationDetail::getExamineId,examineId)
                .orderByAsc(SmsStampRegistrationDetail::getDetailSort))
                .stream()
                .map(detail ->{
                    SmsStampRegistrationDetailVo stampRegistrationDetailVo = new SmsStampRegistrationDetailVo();
                    BeanUtils.copyProperties(detail,stampRegistrationDetailVo);
                    if(!isNullOrEmpty(stampRegistrationDetailVo.getDetailAllowUserId())){
                        SmsUser allowUserInfo = cacheUtil.getUserInfo(stampRegistrationDetailVo.getDetailAllowUserId());
                        SmsStampRegistrationUserVo allowUserVo = new SmsStampRegistrationUserVo();
                        if(allowUserInfo != null){
                            BeanUtils.copyProperties(allowUserInfo,allowUserVo);
                        }
                        stampRegistrationDetailVo.setAllowUserInfo(allowUserVo);
                    }
                    if(detail.getProcessObjectType() == STAMP_OBJECT_TYPE_PERSON){
                        SmsUser allowUser = cacheUtil.getUserInfo(detail.getProcessObjectId());
                        if(allowUser != null) {
                            stampRegistrationDetailVo.setObjectName(allowUser.getRealName());
                            stampRegistrationDetailVo.setObjectPic(allowUser.getUserPic());
                        }
                    }else {
                        SmsRole smsRole = smsRoleMapper.selectById(detail.getProcessObjectId());
                        if(smsRole != null) {
                            stampRegistrationDetailVo.setObjectName(smsRole.getRoleName());
                        }
                    }
                    return stampRegistrationDetailVo;
                })
                .collect(Collectors.toList());
        stampRegistrationVo.setDetailList(stampRegistrationDetailVos);
        return CommonResult.success(stampRegistrationVo);
    }

    @Override
    public ResponseResult getStampRegistrationList(String userId, Integer examine_type, Integer pageNum, Integer pageSize,String search_str) {
        if(isNullOrEmpty(examine_type)){
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        List<SmsStampRegistrationVo> respList = new ArrayList<>();
        int total = 0;
        //已发起的数据
        if(examine_type == STAMP_TYPE_APPLY){
            Page<SmsStampRegistration> page = new Page<>(pageNum,pageSize);
            QueryWrapper<SmsStampRegistration> stampRegistrationQueryWrapper = new QueryWrapper<>();
            stampRegistrationQueryWrapper.lambda()
                    .eq(SmsStampRegistration::getStampApplyUserId,userId)
                    .orderByDesc(SmsStampRegistration::getCreateTime);
            if(!isNullOrEmpty(search_str)) {
                List<String> userIds = smsUserMapper.selectList(new QueryWrapper<SmsUser>()
                        .lambda()
                        .like(SmsUser::getRealName, search_str))
                        .stream()
                        .map(SmsUser::getId).collect(Collectors.toList());
                stampRegistrationQueryWrapper.lambda().and(i -> {
                    i.like(SmsStampRegistration::getStampingReason,search_str);
                    if (userIds.size() > 0) {
                        i.or().in(SmsStampRegistration::getStampApplyUserId, userIds);
                    }
                });
            }
            smsStampRegistrationMapper.selectPage(page,stampRegistrationQueryWrapper);
            respList = page.getRecords()
                    .stream()
                    .map(smsStampRegistration -> {
                        SmsStampRegistrationVo stampRegistrationVo = new SmsStampRegistrationVo();
                        BeanUtils.copyProperties(smsStampRegistration,stampRegistrationVo);
                        stampRegistrationVo.setExamineId(smsStampRegistration.getId());
                        SmsUser applyUserInfo = cacheUtil.getUserInfo(smsStampRegistration.getStampApplyUserId());
                        SmsStampRegistrationUserVo applyUserVo = new SmsStampRegistrationUserVo();
                        if(applyUserInfo != null){
                            BeanUtils.copyProperties(applyUserInfo,applyUserVo);
                        }
                        stampRegistrationVo.setApplyUserInfo(applyUserVo);
                        return stampRegistrationVo;
                    })
                    .collect(Collectors.toList());
            total = (int)page.getTotal();
        }else if(examine_type == STAMP_TYPE_ALLOWED){
            Page<SmsStampRegistrationMpjVo> page = new Page<>(pageNum,pageSize);
            MPJLambdaWrapper<SmsStampRegistrationDetail> mpjLambdaWrapper = new MPJLambdaWrapper<>();
            mpjLambdaWrapper.selectAll(SmsStampRegistrationDetail.class)
                    .selectAll(SmsStampRegistration.class)
                    .selectAs(SmsStampRegistration::getCreateTime,"declarationTime")
                    .selectAs(SmsStampRegistrationDetail::getId,"detailId")
                    .leftJoin(SmsStampRegistration.class,SmsStampRegistration::getId,SmsStampRegistrationDetail::getExamineId)
                    .eq(SmsStampRegistrationDetail::getDetailAllowUserId,userId)
//                    .orderByDesc(SmsStampRegistration::getCreateTime)
                    .orderByDesc(SmsStampRegistrationDetail::getDetailAllowTime);
            mpjLambdaWrapper.and(wrapper ->{
                wrapper.eq(SmsStampRegistrationDetail::getDetailAllowStatus,STAMP_STATUS_PASS)
                        .or()
                        .eq(SmsStampRegistrationDetail::getDetailAllowStatus,STAMP_STATUS_DENY);
            });
            if(!isNullOrEmpty(search_str)) {
                List<String> userIds = smsUserMapper.selectList(new QueryWrapper<SmsUser>()
                        .lambda()
                        .like(SmsUser::getRealName, search_str))
                        .stream()
                        .map(SmsUser::getId).collect(Collectors.toList());
                mpjLambdaWrapper.and(i -> {
                    i.like(SmsStampRegistration::getStampingReason,search_str);
                    if (userIds.size() > 0) {
                        i.or().in(SmsStampRegistration::getStampApplyUserId, userIds);
                    }
                });
            }
            smsStampRegistrationMpjMapper.selectJoinPage(page,SmsStampRegistrationMpjVo.class,mpjLambdaWrapper);
            respList = page.getRecords()
                    .stream()
                    .map(smsExamineMPJResp ->{
                        SmsStampRegistrationVo stampRegistrationVo = new SmsStampRegistrationVo();
                        BeanUtils.copyProperties(smsExamineMPJResp,stampRegistrationVo);
                        stampRegistrationVo.setCreateTime(smsExamineMPJResp.getCreateTime());

                        SmsUser applyUserInfo = cacheUtil.getUserInfo(smsExamineMPJResp.getStampApplyUserId());
                        SmsStampRegistrationUserVo applyUserVo = new SmsStampRegistrationUserVo();
                        if(applyUserInfo != null){
                            BeanUtils.copyProperties(applyUserInfo,applyUserVo);
                        }
                        stampRegistrationVo.setApplyUserInfo(applyUserVo);

                        SmsUser allowUserInfo = cacheUtil.getUserInfo(stampRegistrationVo.getDetailAllowUserId());
                        SmsStampRegistrationUserVo allowUserVo = new SmsStampRegistrationUserVo();
                        if(allowUserInfo != null){
                            BeanUtils.copyProperties(allowUserInfo,allowUserVo);
                        }
                        stampRegistrationVo.setAllowUserInfo(allowUserVo);
                        return stampRegistrationVo;
                    })
                    .collect(Collectors.toList());
            total = (int)page.getTotal();
        }else if(examine_type == STAMP_TYPE_ALLOW_WAIT_ME){
            List<String> roleList = cacheUtil.getRoleList(userId);//获取所有待审批申请流程节点
            List<SmsStampRegistrationDetail> allDetailList = smsStampRegistrationDetailMapper.selectList(
                    new QueryWrapper<SmsStampRegistrationDetail>()
                    .lambda()
                    .eq(SmsStampRegistrationDetail::getDetailAllowStatus, STAMP_STATUS_WAIT_ALLOW));

            List<SmsStampRegistrationDetail> filterDetailList = allDetailList.stream()
                    .filter(detail -> {
                        if(detail.getProcessIsApplicantEdit()){
                            if (!detail.getProcessObjectId().equals(userId)) {
                                return false;
                            }
                        }else {
                            if (detail.getProcessObjectType() == STAMP_OBJECT_TYPE_PERSON) {
                                if (!detail.getProcessObjectId().equals(userId)) {
                                    return false;
                                }
                            } else {
                                List<String> filterRoleList = roleList.stream().filter(role -> role.equals(detail.getProcessObjectId())).collect(Collectors.toList());
                                if (filterRoleList.size() < 1) {
                                    return false;
                                }
                            }
                        }

                        if (detail.getDetailSort().equals(1)) {
                            return true;
                        }
                        //判断上一个流程节点是否完成
                        SmsStampRegistrationDetail preDetail =
                                smsStampRegistrationDetailMapper.selectOne(new QueryWrapper<SmsStampRegistrationDetail>()
                                        .lambda()
                                        .eq(SmsStampRegistrationDetail::getExamineId, detail.getExamineId())
                                        .eq(SmsStampRegistrationDetail::getDetailSort, detail.getDetailSort() - 1)
                                        .eq(SmsStampRegistrationDetail::getDetailAllowStatus, STAMP_STATUS_PASS));
                        if (preDetail == null || isNullOrEmpty(preDetail.getId())) {
                            return false;
                        }
                        return true;
                    })
                    .collect(Collectors.toList());
            if (filterDetailList.size() > 0) {
                List<String> detailIDList = filterDetailList.stream().map(SmsStampRegistrationDetail::getId).collect(Collectors.toList());

                Page<SmsStampRegistrationMpjVo> page = new Page<>(pageNum, pageSize);
                MPJLambdaWrapper<SmsStampRegistrationDetail> mpjLambdaWrapper = new MPJLambdaWrapper<>();
                mpjLambdaWrapper.selectAll(SmsStampRegistrationDetail.class)
                        .selectAll(SmsStampRegistration.class)
                        .selectAs(SmsStampRegistration::getCreateTime, "declarationTime")
                        .selectAs(SmsStampRegistrationDetail::getId, "detailId")
                        .leftJoin(SmsStampRegistration.class, SmsStampRegistration::getId, SmsStampRegistrationDetail::getExamineId)
                        .in(SmsStampRegistrationDetail::getId, detailIDList)
                        .orderByDesc(SmsStampRegistration::getCreateTime)
                        .orderByDesc(SmsStampRegistrationDetail::getDetailAllowTime);
                if(!isNullOrEmpty(search_str)) {
                    List<String> userIds = smsUserMapper.selectList(new QueryWrapper<SmsUser>()
                            .lambda()
                            .like(SmsUser::getRealName, search_str))
                            .stream()
                            .map(SmsUser::getId).collect(Collectors.toList());
                    mpjLambdaWrapper.and(i -> {
                        i.like(SmsStampRegistration::getStampingReason,search_str);
                        if (userIds.size() > 0) {
                            i.or().in(SmsStampRegistration::getStampApplyUserId, userIds);
                        }
                    });
                }
                smsStampRegistrationMpjMapper.selectJoinPage(page, SmsStampRegistrationMpjVo.class, mpjLambdaWrapper);

                respList = page.getRecords()
                        .stream()
                        .map(smsExamineMPJResp -> {
                            SmsStampRegistrationVo smsExamineResp = new SmsStampRegistrationVo();
                            BeanUtils.copyProperties(smsExamineMPJResp, smsExamineResp);
                            smsExamineResp.setCreateTime(smsExamineMPJResp.getCreateTime());

                            SmsUser applyUser = cacheUtil.getUserInfo(smsExamineResp.getStampApplyUserId());
                            SmsStampRegistrationUserVo smsExamineUserResp = new SmsStampRegistrationUserVo();
                            if (applyUser != null) {
                                BeanUtils.copyProperties(applyUser, smsExamineUserResp);
                            }
                            smsExamineResp.setApplyUserInfo(smsExamineUserResp);

                            return smsExamineResp;
                        })
                        .collect(Collectors.toList());
                total = (int) page.getTotal();
            }
        }
        return CommonResult.success(respList,total);
    }

    @Override
    @Async
    public Future<ResponseResult> tableDownload(String apply_id, HttpServletResponse response) {
        SmsStampRegistration stampRegistration = smsStampRegistrationMapper.selectById(apply_id);
        if (stampRegistration == null || stampRegistration.getId() == null) {
            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.STAMP_REGISTRATION_NOT_EXIST));
        }
//        if (stampRegistration.getAllowStatus() == STAMP_STATUS_WAIT_ALLOW) {
//            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.STAMP_REGISTRATION_DOWNLOAD_FAIL));
//        }

        String OSName = System.getProperty("os.name");
        String filePath = OSName.toLowerCase().startsWith("win") ? fileSavePathConstant.getFILE_DOWNLOAD_PATH()
                : fileSavePathConstant.getFILE_DOWNLOAD_PATH_LINUX();

        String newFilePath = filePath + apply_id + ".docx";
        String pdfFilePath = filePath + apply_id + ".pdf";

        File pdfFile = new File(pdfFilePath);

//        if (!pdfFile.exists()) {
            try {


                Map<String, Object> map = new HashMap<>();
                List<String> picTagList = new ArrayList<>();
                map.put("stampReason", stampRegistration.getStampingReason());
                map.put("remarks", filterResultNull(stampRegistration.getRemarks()));
                //申请人签字
                String[] splitStrName = stampRegistration.getSign().split("=");
                String applyFileName = splitStrName[splitStrName.length - 1];
                File applyFile = new File(filePath + applyFileName);
                InputStream applyInputStream = new FileInputStream(applyFile);
                PictureRenderData picture = Pictures.ofStream(applyInputStream,
                        PictureType.PNG).size(60, 30).create();
                map.put("name", picture);
                picTagList.add("name");

                map.put("createTime",TimeUtil.DateHanZiSimpleFormat(stampRegistration.getCreateTime()));
                //获取初始流程
                List<SmsStampRegistrationProcess> processList = smsStampRegistrationProcessMapper.selectList(
                        new QueryWrapper<SmsStampRegistrationProcess>()
                                .lambda()
                                .orderByAsc(SmsStampRegistrationProcess::getProcessSort));
                if (processList == null || processList.size() < 1) {
                    return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.FAIL));
                }

                //获取申请流程
                List<SmsStampRegistrationDetail> detailList = smsStampRegistrationDetailMapper.selectList(
                        new QueryWrapper<SmsStampRegistrationDetail>()
                                .lambda()
                                .eq(SmsStampRegistrationDetail::getExamineId, apply_id));
                for (SmsStampRegistrationProcess process : processList) {
                    List<SmsStampRegistrationDetail> filterDetail = detailList
                            .stream()
                            .filter(detail -> detail.getProcessId().equals(process.getId()))
                            .collect(Collectors.toList());
                    if (filterDetail.size() > 0) {
                        SmsStampRegistrationDetail detail = filterDetail.get(0);
                        if (detail.getDetailAllowStatus() == STAMP_STATUS_PASS) {
                            map.put("allowStatus" + process.getProcessSort() , "同意");
                        } else if (detail.getDetailAllowStatus() == STAMP_STATUS_DENY) {
                            map.put("allowStatus" + process.getProcessSort() , "拒绝");
                        } else {
                            map.put("allowStatus" + process.getProcessSort() , "");
                        }

                        map.put("allowOption" + process.getProcessSort() , detail.getDetailAllowOpinion());
                        //审批时间
                        if(isNullOrEmpty(detail.getDetailAllowTime())) {
                            map.put("allowTime" + process.getProcessSort() , "");
                        }else {
                            map.put("allowTime" + process.getProcessSort() , TimeUtil.DateHanZiSimpleFormat(detail.getDetailAllowTime()));
                        }

                        //添加签名
                        if (isNullOrEmpty(detail.getDetailAllowSign())) {
                            map.put("allowSign" + process.getProcessSort() , "");
                        } else {
                            String[] splitStr = detail.getDetailAllowSign().split("=");
                            String fileName = splitStr[splitStr.length - 1];
                            File file = new File(filePath + fileName);
                            if(file.exists()) {
                                InputStream inputStream = new FileInputStream(file);
                                PictureRenderData pictures = Pictures.ofStream(inputStream,
                                        PictureType.PNG).size(60, 30).create();

                                map.put("allowSign" + process.getProcessSort(), pictures);
                                picTagList.add("allowSign" + process.getProcessSort());
                            }
                        }

                        //添加印章
                        if (isNullOrEmpty(detail.getDetailAllowStamp())) {
                            map.put("allowStamp" + process.getProcessSort() , "");
                        } else {
                            String[] splitStr = detail.getDetailAllowStamp().split("=");
                            String fileName = splitStr[splitStr.length - 1];
                            File file = new File(filePath + fileName);
                            if(file.exists()) {
                                InputStream inputStream = new FileInputStream(file);
                                PictureRenderData pictures = Pictures.ofStream(inputStream,
                                        PictureType.PNG).size(60, 30).create();

                                map.put("allowStamp" + process.getProcessSort(), pictures);
                                picTagList.add("allowStamp" + process.getProcessSort());
                            }
                        }
                    } else {
                        map.put("allowStatus" + process.getProcessSort() , "");
                        map.put("allowOption" + process.getProcessSort() , "");
                        map.put("allowSign" + process.getProcessSort() , "");
                        map.put("allowStamp" + process.getProcessSort() , "");
                        map.put("allowTime" + process.getProcessSort() , "");
                    }
                }

                InputStream is = null;

                ClassPathResource resource = new ClassPathResource("applyTemplates/stampRegistrationTemplate.docx");
                is = resource.getInputStream();
                FileOutputStream outputStream = new FileOutputStream(newFilePath);
                XWPFTemplate template = XWPFTemplate.compile(is);

                //配置图片标签
                Configure config = template.getConfig();
                for (String tag:picTagList
                ) {
                    config.customPolicy(tag,new PictureRenderPolicy());
                }
                template.render(map);

                template.write(outputStream);

                is.close();
                outputStream.close();
                template.close();

                //word转pdf
                File destOri = new File(newFilePath);
                FileInputStream fileInputStream = new FileInputStream(destOri);
                FileOutputStream fileOutputStream = new FileOutputStream(pdfFilePath);

                Document document = new Document();
                document.loadFromStream(fileInputStream, FileFormat.Docx);


                response.setCharacterEncoding("utf-8");
                response.setContentType("application/vnd.pdf;charset=utf-8");
                response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("印章使用登记预览.pdf", "utf-8"));
                response.setHeader("file-name", URLEncoder.encode("印章使用登记预览.pdf", "utf-8"));
                response.setHeader("file-type", "download");
                response.setHeader("Access-Control-Expose-Headers", "file-type,file-name");

                //保存为PDF
//                document.saveToFile(pdfFilePath, FileFormat.PDF);
                document.saveToStream(response.getOutputStream(), FileFormat.PDF);

                fileInputStream.close();
                fileOutputStream.close();
                document.close();

                log.debug("文件生成完成!");
            } catch (Exception e) {
                e.printStackTrace();
                return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.FAIL));
            }
//        }
//        try {
//            // 加载PDF文档
//            PDDocument doc = PDDocument.load(pdfFile);
//            doc.setAllSecurityToBeRemoved(true);
//            // 创建水印
//            String watermark = "南充电影工业职业学院";
//            PDPageContentStream contentStream;
//
//            for (PDPage page : doc.getPages()) {
//                contentStream = new PDPageContentStream(doc, page, PDPageContentStream.AppendMode.APPEND, true, true);
//
//                //加载字体
//                ClassPathResource resource = new ClassPathResource("fonts/123.ttf");
//                InputStream is = resource.getInputStream();
//                PDFont font = PDType0Font.load(doc, is);
//
//
//                int startX = 0; // 起始位置 x 坐标
//                int startY = 0; // 起始位置 y 坐标
//                float angle = -45; // 角度
//                float interval = 220; // 间隔
//                float opacity = 0.3f; // 透明度
//                int colorR = 127; // 颜色 red 值
//                int colorG = 127; // 颜色 green 值
//                int colorB = 127; // 颜色 blue 值
//
//                //透明的
//                PDExtendedGraphicsState r0 = new PDExtendedGraphicsState();
//                r0.setNonStrokingAlphaConstant(opacity);
//                r0.setAlphaSourceFlag(true);
//                contentStream.setGraphicsStateParameters(r0);
//
//                //水印颜色
//                contentStream.setNonStrokingColor(colorR, colorG, colorB);
//                contentStream.beginText();
//                contentStream.setFont(font, 30f);
//
//                Integer x_times =(int) Math.ceil(page.getMediaBox().getWidth()/interval);
//                Integer y_times = (int) Math.ceil(page.getMediaBox().getHeight()/interval);
//                for (int x = startX; x <= x_times; x ++) {
//                    for (int y = startY; y <= y_times; y ++) {
//                        contentStream.setTextRotation(angle, (x*interval), (y*interval));
//                        contentStream.showText(watermark);
//                    }
//                }
//                contentStream.endText();
//                contentStream.restoreGraphicsState();
//                contentStream.close();
//                is.close();
//            }
//
//
//            response.setCharacterEncoding("utf-8");
//            response.setContentType("application/vnd.pdf;charset=utf-8");
//            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("印章使用登记预览.pdf", "utf-8"));
//            response.setHeader("file-name", URLEncoder.encode("印章使用登记预览.pdf", "utf-8"));
//            response.setHeader("file-type", "download");
//            response.setHeader("Access-Control-Expose-Headers", "file-type,file-name");
//
//            //刷新缓冲
//            response.flushBuffer();
//            // 保存PDF文档
//            doc.save(response.getOutputStream());
//            doc.close();
//        } catch (Exception e) {
//            e.printStackTrace();
//            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.FAIL));
//        }
        return new AsyncResult<>(CommonResult.success());
    }

    private String filterResultNull(String resultStr) {
        if (resultStr.equals("null")) {
            return "";
        }
        return resultStr;
    }

    @Override
    public ResponseResult getAllStampRegistrationList(Integer allowStatus, String applyName, Integer pageNum, Integer pageSize) {
        Page<SmsStampRegistration> page = new Page<>(pageNum,pageSize);
        LambdaQueryWrapper<SmsStampRegistration> queryWrapper = new LambdaQueryWrapper<>();
        if(!isNullOrEmpty(allowStatus)){
            queryWrapper.eq(SmsStampRegistration::getAllowStatus,allowStatus);
        }
        if(!isNullOrEmpty(applyName)){
            List<String> userIds = smsUserMapper.selectList(new QueryWrapper<SmsUser>()
                    .lambda()
                    .like(SmsUser::getRealName, applyName))
                    .stream()
                    .map(SmsUser::getId).collect(Collectors.toList());
            if(userIds.size() > 0) {
                queryWrapper.in(SmsStampRegistration::getStampApplyUserId, userIds);
            }
        }
        queryWrapper.orderByDesc(SmsStampRegistration::getCreateTime);
        smsStampRegistrationMapper.selectPage(page,queryWrapper);
        List<SmsStampRegistrationVo> registrationList = new ArrayList<>();
        registrationList = page.getRecords()
                .stream()
                .map(registration ->{
                    SmsStampRegistrationVo smsStampRegistrationVo = new SmsStampRegistrationVo();
                    BeanUtils.copyProperties(registration,smsStampRegistrationVo);
                    smsStampRegistrationVo.setExamineId(registration.getId());
                    SmsUser userInfo = cacheUtil.getUserInfo(registration.getStampApplyUserId());
                    SmsStampRegistrationUserVo userVo = new SmsStampRegistrationUserVo();
                    if(userInfo != null){
                        BeanUtils.copyProperties(userInfo,userVo);
                    }
                    smsStampRegistrationVo.setApplyUserInfo(userVo);
                    return smsStampRegistrationVo;
                })
                .collect(Collectors.toList());
        int total = (int)page.getTotal();
        return CommonResult.success(registrationList,total);
    }

    @Override
    @Async
    public Future<ResponseResult> exportExamineHistoryList(SmsStampRegistrationHistoryReq req, HttpServletResponse response) {
        if (isNullOrEmpty(req.getIsExportProcess())) {
            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
        }
        try {
            LambdaQueryWrapper<SmsStampRegistration> queryWrapper = new LambdaQueryWrapper<>();
            if (!isNullOrEmpty(req.getExamineId())) {
                queryWrapper.eq(SmsStampRegistration::getId, req.getExamineId());
            }
            if (!isNullOrEmpty(req.getApplyName())) {
                List<String> userIds = smsUserMapper.selectList(new QueryWrapper<SmsUser>()
                        .lambda()
                        .like(SmsUser::getRealName, req.getApplyName()))
                        .stream()
                        .map(SmsUser::getId).collect(Collectors.toList());
                if(userIds.size() > 0) {
                    queryWrapper.in(SmsStampRegistration::getStampApplyUserId, userIds);
                }
            }
            if (!isNullOrEmpty(req.getAllowStatus())) {
                queryWrapper.like(SmsStampRegistration::getAllowStatus, req.getAllowStatus());
            }
            queryWrapper.orderByDesc(SmsStampRegistration::getCreateTime);
            List<SmsStampRegistration> list = smsStampRegistrationMapper.selectList(queryWrapper);
            //表头数据
            String[] header = req.getLimitColumn().toArray(new String[0]);
            double sheetNum;
            //声明一个工作簿
            HSSFWorkbook workbook = new HSSFWorkbook();
            if (list != null && list.size() > 0) {
                sheetNum = Math.ceil((double) list.size() / PER_SHEET_NUM);
                for (int k = 0; k < sheetNum; k++) {
                    //生成一个表格，设置表格名称为"资源导出表"
                    HSSFSheet sheet = workbook.createSheet("印章使用登记记录导出表" + (k + 1));

                    //设置表格列宽度为10个字节
                    sheet.setDefaultColumnWidth(12);
                    //创建标题的显示样式
                    HSSFCellStyle headerStyle = workbook.createCellStyle();
                    headerStyle.setFillForegroundColor(IndexedColors.YELLOW.index);
                    headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

                    HSSFFont f = workbook.createFont();
                    f.setFontHeightInPoints((short) 10);//字号
                    f.setBold(true);//加粗
                    headerStyle.setFont(f);
                    //创建第一行表头
                    HSSFRow headrow = sheet.createRow(0);

                    //遍历添加表头(下面模拟遍历学生，也是同样的操作过程)
                    for (int i = 0; i < header.length + 1; i++) {
                        //创建一个单元格
                        HSSFCell cell = headrow.createCell(i);

                        if (i == 0) {
                            //创建一个内容对象
                            HSSFRichTextString text = new HSSFRichTextString("序号");
                            //将内容对象的文字内容写入到单元格中
                            cell.setCellValue(text);
                            cell.setCellStyle(headerStyle);
                            continue;
                        }
                        //创建一个内容对象
                        String header1 = apiModelUtil.getFieldValueByFieldName(SmsStampRegistration.class, header[i - 1]);
                        HSSFRichTextString text = new HSSFRichTextString(header1);

                        //将内容对象的文字内容写入到单元格中
                        cell.setCellValue(text);
                        cell.setCellStyle(headerStyle);
                    }

                    //判断是否需要添加流程表头
                    if (req.getIsExportProcess() == EXPORT_PROCESS_TRUE) {
                        List<SmsStampRegistrationProcess> processList =
                                smsStampRegistrationProcessMapper.selectList(new QueryWrapper<>());
                        if (processList != null && processList.size() > 0) {
                            Integer origin_num = header.length + 1;
                            for (SmsStampRegistrationProcess process : processList) {
                                String process_name = process.getProcessName();
                                addProcessTableHead(headrow, headerStyle, origin_num, process_name);
                                origin_num += 4;
                            }
                        }
                    }

                    int range = PER_SHEET_NUM;
                    if (k + 1 == sheetNum) {
                        range = list.size() - (PER_SHEET_NUM) * k;
                    }
                    for (int i = 0; i < range; i++) {
                        //创建一行
                        HSSFRow row1 = sheet.createRow(i + 1);
                        SmsStampRegistration paymentExamine = list.get((PER_SHEET_NUM) * k + i);
                        Map map = JSONObject.parseObject(JSON.toJSONString(paymentExamine), Map.class);
                        row1.createCell(0).setCellValue(new HSSFRichTextString(i + 1 + ""));
                        for (int j = 0; j < header.length; j++) {
                            String rowContent = "";
                            if (map.get(header[j]) instanceof Long) {
                                rowContent = TimeUtil.DateformatTimestamp((long) map.get(header[j]));
                            } else {
                                if (header[j].equals("stampApplyUserId")){
                                    SmsUser smsUser = cacheUtil.getUserInfo(paymentExamine.getStampApplyUserId());
                                    if (smsUser!=null){
                                        rowContent = smsUser.getRealName();
                                    }else{
                                        rowContent = "";
                                    }
                                } else{
                                    rowContent = String.valueOf(map.get(header[j]));
                                }
                            }
                            row1.createCell(j + 1).setCellValue(new HSSFRichTextString(rowContent));
                        }

                        if (req.getIsExportProcess() == EXPORT_PROCESS_TRUE) {
                            List<SmsStampRegistrationProcess> processList =
                                    smsStampRegistrationProcessMapper.selectList(new QueryWrapper<>());
                            if (processList != null && processList.size() > 0) {
                                Integer origin_num = header.length + 1;
                                for (SmsStampRegistrationProcess process : processList) {
                                    SmsStampRegistrationDetail detail =
                                            smsStampRegistrationDetailMapper.selectOne(new QueryWrapper<SmsStampRegistrationDetail>()
                                                    .lambda()
                                                    .eq(SmsStampRegistrationDetail::getExamineId, paymentExamine.getId())
                                                    .eq(SmsStampRegistrationDetail::getProcessId, process.getId()));
                                    if (detail == null || detail.getId() == null) {
                                        origin_num += 4;
                                    } else {
                                        //审批人
                                        SmsUser user = cacheUtil.getUserInfo(detail.getDetailAllowUserId());
                                        if (user == null) {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(""));
                                        } else {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(user.getRealName()));
                                        }

                                        //审批时间
                                        Date allow_time = detail.getDetailAllowTime();
                                        if (allow_time == null) {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(""));
                                        } else {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(TimeUtil.DateHanZiSimpleFormat(allow_time)));
                                        }

                                        //审批状态
                                        Integer allow_status = detail.getDetailAllowStatus();
                                        if (allow_status == STAMP_STATUS_PASS) {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString("同意"));
                                        } else if (allow_status == STAMP_STATUS_DENY) {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString("拒绝"));
                                        } else {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(""));
                                        }

                                        //审批意见
                                        String allow_option = detail.getDetailAllowOpinion();
                                        if (isNullOrEmpty(allow_option)) {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(""));
                                        } else {
                                            row1.createCell(origin_num++).setCellValue(new HSSFRichTextString(allow_option));
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

//            response.reset();
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("印章使用登记记录导出表.xlsx", "utf-8"));
            response.setCharacterEncoding("utf-8");
            response.setHeader("file-type", "download");
            response.setHeader("file-name", URLEncoder.encode("印章使用登记记录导出表.xlsx", "utf-8"));
            response.setHeader("Access-Control-Expose-Headers", "file-type,file-name");
//            //刷新缓冲
            response.flushBuffer();
            //workbook将Excel写入到response的输出流中，供页面下载
            OutputStream os = response.getOutputStream();
            workbook.write(os);

            workbook.close();
            os.close();
        } catch (Exception e) {
            e.printStackTrace();
            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.FAIL));
        }
        return null;
    }

    private void addProcessTableHead(HSSFRow headRow, HSSFCellStyle headerStyle, Integer origin_cell_num, String originHeadContent) {
        Integer cell_num = origin_cell_num;

        setTableHead(headRow, headerStyle, cell_num++, originHeadContent + "审批人");
        setTableHead(headRow, headerStyle, cell_num++, originHeadContent + "审批时间");
        setTableHead(headRow, headerStyle, cell_num++, originHeadContent + "审批状态");
        setTableHead(headRow, headerStyle, cell_num, originHeadContent + "审批意见");

    }

    private void setTableHead(HSSFRow headRow, HSSFCellStyle headerStyle, Integer cell_num, String headContent) {
        HSSFCell cell = headRow.createCell(cell_num);
        //创建一个内容对象
        HSSFRichTextString text = new HSSFRichTextString(headContent);

        //将内容对象的文字内容写入到单元格中
        cell.setCellValue(text);
        cell.setCellStyle(headerStyle);
    }


}
